package com.buba.springcloud.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpMode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.buba.springcloud.config.Constants;
import com.buba.springcloud.config.SftpUtil;
import com.buba.springcloud.mapper.DocumentMapper;
import com.buba.springcloud.pojo.Document;
import com.buba.springcloud.service.IDocumentService;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;

import static com.buba.springcloud.config.Constants.localPath;
import static com.buba.springcloud.config.Constants.remotePath;

@Slf4j
@Service
public class DocumentServiceImpl extends ServiceImpl<DocumentMapper, Document> implements IDocumentService {

    @Autowired
    SftpUtil sftpUtil;

    @Override
    public String upload(MultipartFile mf, Integer userId) {
        String url = "";
        try {
            String curFileName = mf.getOriginalFilename();
            String type = mf.getContentType();
            String shortName = curFileName.substring(0,curFileName.lastIndexOf("."));
//            取消名称后带时间戳
//            String newName = shortName+ "_"+String.valueOf(System.currentTimeMillis()) + curFileName.substring(curFileName.lastIndexOf("."));
            //判断类型
            String targetType = "application/pdf";
            if (!targetType.equals(type)) {
                log.error("文档类型不支持");
            }

            //判断图片大小
            //判断长宽
//            BufferedImage image = ImageIO.read(mf.getInputStream());
//            if (image == null) {
//                throw new FebsException("图片无法识别");
//            }

//            int curWidth = image.getWidth();
//            int curHeight = image.getHeight();
//            int targetMaxWidth = 300;
//            int targetHeigth = 720;
//            if (curWidth <= targetMaxWidth || curHeight != targetHeigth) {
//                throw new FebsException("上传的文件尺寸不符合要求，必须是：宽不超过" + targetMaxWidth + "px, 高等于" + targetHeigth+ "px");
//            }

            //由于前端读取pdf不方便，所不建立新文件夹
//            String dirName = DateUtil.format(new Date(), "yyyy-MM-dd");
//            String basePath = "http://127.0.0.1:8080/";
            //服务器存放路径，开头带/，表示绝对根目录开始
//            File file = FileUtil.file(FileUtil.mkdir("/media/pdf/" + dirName), newName);
// 获取static目录获取static就可以完成上传功能了
//            String realPath = ResourceUtils.getURL("classpath:").getPath() + "static";

//            通过MultipartFile.transferTo方法将前端传来的数据存到本机
//            String realPath = "/Users/wanghong/Desktop/文档发布/uploads";
            File file = FileUtil.file(FileUtil.mkdir(localPath), shortName+".pdf");
            mf.transferTo(file);
            log.info("保存成功");

//            异地保存
//            如果使用的是自建服务器+云服务器，需要继续copy一份上传至云服务器，下面使用的是jcraft方案上传
//            FileInputStream in = new FileInputStream(file);
//            sftpUtil.upload(remotePath,shortName+".pdf", in);
//            in.close();
//            log.info("上传成功");

//            hutool的Ftp方式上传，测试不通
//            Ftp ftp = null;
//            try {
//                //建立FTP连接
//                ftp = new Ftp("47.98.120.14",22," root ", "whSZD106", Charset.defaultCharset(), FtpMode.Passive);
//                boolean  isUp = ftp.upload(Constants.remotePath, FileUtil.file(Constants.localPath));
//                if(isUp){
//                    System.out.println("文件上传成功");
//                }
//            }catch (Exception e){
//                e.printStackTrace();
//            }finally {
//                //释放ftp连接
//                if (ftp!=null){
//                    ftp.close();
//                }
//                log.info("成功存放到服务器");
//            }

            /**
             * 保存记录到数据库
             */
            Document document = new Document();
            document.setUserId(userId);
            document.setName(shortName);
//            用户设置类型
            document.setType(1);
            document.setUrl("/literature/"+shortName+".pdf");
            document.setCreatedTime(new Date());
//            用户选择库中图片
            document.setMainImage("/images/%E5%9B%BE%E6%96%87%E4%B8%BB%E5%9B%BE.jpeg");
//            前端用户选择库中链接商品ids
            document.setProductIds("40,38");
            log.info("document:"+document);
//            未解决重复插入数据的问题，改成采用数据库唯一索引配置方案
            boolean r = this.saveOrUpdate(document);
            log.info("数据保存结果:"+String.valueOf(r));
//            this.baseMapper.insert(document);
        } catch (Exception e) {
            log.error("上传失败");
            return "null";
        }
        //待返回服务器的文件地址，暂未对url处理赋值
        return url;
    }

    @Override
    public List<Document> selectList(Integer userId) {
        QueryWrapper<Document> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.orderByDesc("created_time");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public Document detailByName(String name) {
        QueryWrapper<Document>queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        //拼接image的url
        Document aResult = this.baseMapper.selectOne(queryWrapper);
        aResult.setUrl(Constants.ipAddr+aResult.getUrl());
        aResult.setMainImage(Constants.ipAddr+aResult.getMainImage());
        return aResult;
    }

//    单独创建pdf分片方法
    @Override
    public void loadPDFByPage(String pdfName, HttpServletResponse response, HttpServletRequest request) {
        File pdf =null;
        try{
            //      比较：通过本机绝对路径是否比域名访问速度快，new File()不可以网络路径
//        File pdf = ResourceUtils.getFile("classpath:bigfile.pdf");
//        开发环境
//            pdf = new File("/Users/wanghong/Desktop/文档发布/"+pdfName);
//        上线配置，linux路径
//         pdf = new File("/usr/local/guides-web/literature/"+pdfName);
         pdf = new File(localPath+"/"+pdfName);
        }catch (Exception e){e.printStackTrace();}

        try (
                InputStream is = new FileInputStream(pdf);
                BufferedInputStream bis = new BufferedInputStream(is);
                OutputStream os = response.getOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(os)) {
//            System.out.println(request.getHeader("range")+"----range");//bytes=14680064-15728639----range
            // 下载的字节范围
            int startByte, endByte, totalByte;
            if (request != null && request.getHeader("range") != null) {
                // 断点续传
                String[] range = request.getHeader("range").replaceAll("[^0-9\\-]", "").split("-");
                // 文件总大小
                totalByte = is.available();
                // 下载起始位置
                startByte = Integer.parseInt(range[0]);
                // 下载结束位置
                if (range.length > 1) {
                    endByte = Integer.parseInt(range[1]);
                } else {
                    endByte = totalByte - 1;
                }
//                System.out.println(startByte+"---come in-----"+endByte);//14680064---come in-----15728639
                // 返回http状态
                response.setStatus(206);
            } else {
                // 正常下载
                // 文件总大小
                totalByte = is.available();
                // 下载起始位置
                startByte = 0;
                // 下载结束位置
                endByte = totalByte - 1;
                // 返回http状态
                response.setHeader("Accept-Ranges", "bytes");
                response.setStatus(200);
            }
            // 需要下载字节数
            int length = endByte - startByte + 1;

            //表明服务器支持分片加载
            response.setHeader("Accept-Ranges", "bytes");

            //Content-Range: bytes 0-65535/408244，表明此次返回的文件范围
            response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + totalByte);

            //告知浏览器这是一个字节流，浏览器处理字节流的默认方式就是下载
            response.setContentType("application/octet-stream");

            //表明该文件的所有字节大小
            response.setContentLength(length);

            //需要设置此属性，否则浏览器默认不会读取到响应头中的Accept-Ranges属性，因此会认为服务器端不支持分片，所以会直接全文下载
            response.setHeader("Access-Control-Expose-Headers", "Accept-Ranges,Content-Range");

            // 响应内容
            bis.skip(startByte);
            int len = 0;
            byte[] buff = new byte[1024 * 64];
            while ((len = bis.read(buff, 0, buff.length)) != -1) {
                if (length <= len) {
                    bos.write(buff, 0, length);
                    break;
                } else {
                    length -= len;
                    bos.write(buff, 0, len);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂时方法实现区分文档和视频
     */
//    @Override
//    public List<Media> selectList(Integer userId) {
//        QueryWrapper<Media> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("userId", userId);
//
//        return null;
//    }

    private static void closeChannel(Channel channel) {
        if (channel != null) {
            if (channel.isConnected()) {
                channel.disconnect();
            }
        }
    }

    private static void closeSession(Session session) {
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }
}
